<?php

use think\facade\Db;
use think\facade\Request;

/*文件上传类*/
class Upload {

    protected $path;

    public function __construct($path = null)
    {
        if(empty($path)){
            //默认应用_控制器_方法。好处是方便知道这些文件由哪些业务产生的
            $this->path = app('http')->getName().'_'.Request::controller(true).'_'.Request::action(true);
        }else{
            $this->path = $path;
        }
    }
    /**
     * 文件上传
     */
    public function save() {
        $hash = request()->post('hash');
        $userInfo = request()->USER_INFO;
        $result = $this->fileValidate();
        if($result['code'] != 1){
            return $result;
        }
        $filesystemConfig = config('filesystem.disks.public');
        if(!empty($hash)){
            if(is_string($hash)){
                $hashArr = explode(',', $hash);
            }
            $attachment = Db::name('common_attachment')->where('hash','in',$hashArr)->order('id desc')->select()->toArray();
            if(!empty($attachment)){
                $alreadyFile = [];
                $alreadyFileHash = [];
                foreach ($attachment as $val){
                    if(file_exists($filesystemConfig['root'].$val['path'])){
                        $alreadyFileHash[$val['hash']] = $val['hash'];
                        $alreadyFile[] = [
                            'fileName'   => $val['original_name'],
                            'fileUrl'    => $val['path'],
                            'sha256'     => $val['hash'],
                            'previewUrl' => request()->domain() . $filesystemConfig['url'] . $val['path']
                        ];
                    }
                }
            }
        }
        $filesData   = [];
        $installData = [];
        $files       = request()->file();
        if(!empty($files)){
            foreach ($files as $key => $file){
                $fileHash = $file->hash('sha256');
                //去掉重复文件
                if(isset($alreadyFileHash) && !empty($alreadyFileHash) && in_array($fileHash, $alreadyFileHash)){
                    continue;
                }
                $attachment = Db::name('common_attachment')->where('hash','=',$fileHash)->order('id desc')->find();
                if(!empty($attachment) && file_exists($filesystemConfig['root'].$attachment['path'])){
                    $savePath = $attachment['path'];
                }else{
                    $savePath = \think\facade\Filesystem::disk('public')->putFile($this->path, $file);
                    if(empty($savePath)){
                        return $this->returnResult(0,'文件保存失败：'.$file->getOriginalName());
                    }
                }
                if(empty($attachment)){
                    $installData[] = [
                        'uid'           => !empty($userInfo['id'])?$userInfo['id']:0,
                        'path'          => $savePath,
                        'hash'          => $fileHash,
                        'type'          => $file->getOriginalMime(),
                        'original_name' => $file->getOriginalName(),
                        'size'          => $_FILES[$key]['size'],
                        'create_time'   => time()
                    ];
                }
                if(!empty($attachment) && !file_exists($filesystemConfig['root'].$attachment['path'])){
                    Db::name('common_attachment')->where('hash','=',$fileHash)->order('id desc')->update([
                        'path'          => $savePath,
                        'update_time'   => time()
                    ]);
                }
                $filesData[] = [
                    'fileName'   => $file->getOriginalName(),
                    'fileUrl'    => $savePath,
                    'sha256'     => $fileHash,
                    'previewUrl' => request()->domain().$filesystemConfig['url'].$savePath
                ];
            }
            if(!empty($installData)){
                try {
                    Db::name('common_attachment')->insertAll($installData);
                }catch (\Exception $e) {
                    //不处理
                }
            }
        }
        if(isset($alreadyFile) && !empty($alreadyFile)){
            $filesData = array_merge($filesData,$alreadyFile);
        }
        if(empty($filesData) && !empty($hash)){
            return $this->returnResult(0,'不支持闪传');
        }
        if(empty($filesData)){
            return $this->returnResult(0,'未上传任何文件');
        }
        return $this->returnResult(1,'上传成功',$filesData);
    }
    /**
     * 删除指定文件和记录
     */
    public function del($fileId) {
        $find = Db::name('common_attachment')->where(['id'=>$fileId])->find();
        if(!$find){
            return $this->returnResult(0,'未找到记录');
        }
        Db::name('common_attachment')->where(['id'=>$fileId])->delete();
        $filesystemConfig = config('filesystem.disks.public');
        if(!file_exists($filesystemConfig['root'].'/'.$find['path'])){
            return $this->returnResult(0,'文件不存在');
        }
        $result = unlink($filesystemConfig['root'].'/'.$find['path']);
        if(!$result){
            return $this->returnResult(0,'删除失败');
        }
        return $this->returnResult(1,'删除成功');
    }
    /**
     * 文件简单验证
     */
    public function fileValidate()
    {
        $imageExt = ['.jpg','.png','.gif'];
        $fileExt  = ['.zip','.rar','.7z','.tar','.xlsx','.xls','.docx','.doc','.txt','.apk','.ipa'];
        $mediaExt = ['.mp3','.wav','.flac','.mp4','.rmvb','.mov'];
        $extArr   = array_merge($imageExt,$fileExt,$mediaExt);
        if(!empty($_FILES)){
            foreach ($_FILES as $val){
                $ext = strrchr($val['name'],'.');
                //格式验证
                if(!in_array($ext, $extArr)){
                    return $this->returnResult(0,"不允许该文件格式：$val[name]");
                }
                //验证大小
                if(in_array($ext, $imageExt)){
                    //5兆
                    if($val['size']>5242880){
                        return $this->returnResult(0,"文件超出大小：$val[name]，只允许5MB");
                    }
                }
                if(in_array($ext, ($fileExt+$mediaExt))){
                    //50兆
                    if($val['size']>50485760){
                        return $this->returnResult(0,"文件超出大小：$val[name]，只允许50MB");
                    }
                }
            }
        }
        return $this->returnResult(1,"验证通过");
    }
    /**
     * 本类统一返回
     */
    private function returnResult($code,$msg,$data = [])
    {
        return [
            'code'=>$code,
            'msg' =>$msg,
            'data'=>$data
        ];
    }
}
